# 将函数存储在模块中
# 使用函数的优点之一是可将代码块与主程序分离。
# 通过给函数指定描述性名称，可让主程序容易理解得多。
# 还可以更进一步，将函数存储在称为模块 的独立文件中，再将模块导入 到主程序中。
# import 语句允许在当前运行的程序文件中使用模块中的代码。

# 通过将函数存储在独立的文件中，可隐藏程序代码的细节，将重点放在程序的高层逻辑上。
# 这还能让你在众多不同的程序中重用函数。
# 将函数存储在独立文件中后，可与其他程序员共享这些文件而不是整个程序。
# 知道如何导入函数还能让你使用其他程序员编写的函数库。


# 导入整个模块
# 要让函数是可导入的，得先创建模块。
# 模块 是扩展名为.py的文件，包含要导入到程序中的代码。

# 下面来创建一个包含函数make_pizza() 的模块。
# 为此，将文件pizza.py中除函数make_pizza() 之外的其他代码删除：
# pizza.py

# def make_pizza(size, *toppings):
# 	"""概述要制作的披萨"""
# 	print(f"\nMaking a {size}-inch pizza with the following toppings:")
# 	for topping in toppings:
# 		print(f"-{topping}")

# 接下来，在pizza.py所在的目录中创建一个名为making_pizzas.py的文件。
# 这个文件导入刚创建的模块，再调用make_pizza() 两次
# making_pizzas.py

# import pizza
# pizza.make_pizza(16, 'pepperoni')
# pizza.make_pizza(12, 'mushroom', 'green peppers', 'extra cheese')

# Python读取这个文件时，代码行import pizza 让Python打开文件pizza.py，
# 并将其中的所有函数都复制到这个程序中。你看不到复制的代码，因为在这个程序即将运行时，
# Python在幕后复制了这些代码。你只需知道，在making_pizzas.py中，可使用pizza.py中定义的所有函数。

# 要调用被导入模块中的函数，可指定被导入模块的名称pizza 和函数名make_pizza() ，并用句点分隔

# 这就是一种导入方法：只需编写一条import 语句并在其中指定模块名，就可在程序中使用该模块中的所有函数。
# 如果使用这种import 语句导入了名为module_name.py的整个模块，就可使用下面的语法来使用其中任何一个函数：
# module_name.function_name()


# 导入特定的函数
# 还可以导入模块中的特定函数，这种导入方法的语法如下：
# from module_name inport function_name
# 通过用逗号分隔函数名，可根据需要从模块中导入任意数量的函数:
# from module_name inport function_0, function_1, function2

# 对于前面的making_pizzas.py示例，如果只想导入要使用的函数，代码将类似于下面这样:
# from pizza import make_pizza
# make_pizza(16, 'pepperoni')
# make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
# 使用这种语法时，调用函数时无须使用句点。
# 由于在import 语句中显式地导入了函数make_pizza() ，调用时只需指定其名称即可。

# 使用as 给函数指定别名
# 如果要导入函数的名称可能与程序中现有的名称冲突，或者函数的名称太长，
# 可指定简短而独一无二的别名 ：函数的另一个名称，类似于外号。
# 要给函数取这种特殊外号，需要在导入它时指定。
# 下面给函数make_pizza() 指定了别名mp() 。
# 这是在import 语句中使用make_pizza as mp 实现的，关键字as 将函数重命名为指定的别名

# from pizza import make_pizza as mp
# mp(16, 'pepperoni')
# mp(12, 'mushrooms', 'green peppers', 'extra cheese')

# 上面的import 语句将函数make_pizza() 重命名为mp() 。
# 在这个程序中，每当需要调用make_pizza() 时，都可简写成mp() 。
# Python将运行make_pizza() 中的代码，避免与这个程序可能包含的函数make_pizza() 混淆。

# 指定别名的通用语法如下：
# from module_name import function_name as fn


# 使用as 给模块指定别名
# 还可以给模块指定别名。通过给模块指定简短的别名（如给模块pizza 指定别名p ），让你能够更轻松地调用模块中的函数。
# 相比于pizza.make_pizza() ，p.make_pizza() 更为简洁：

# import pizza as p
# p.make_pizza(16, 'pepperoni')
# p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

# 上述import 语句给模块pizza 指定了别名p ，但该模块中所有函数的名称都没变。
# 要调用函数make_pizza() ，可编写代码p.make_pizza() 而非pizza.make_pizza() 。
# 这样不仅代码更简洁，还让你不用再关注模块名，只专注于描述性的函数名。
# 这些函数名明确指出了函数的功能，对于理解代码而言，比模块名更重要。

# 给模块指定别名的通用语法如下:
# import module_name as mn


# 导入模块中的所有函数
# 使用星号（* ）运算符可让Python导入模块中的所有函数：
# from pizza import *
# make_pizza(16, 'pepperoni')
# make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')

# import 语句中的星号让Python将模块pizza 中的每个函数都复制到这个程序文件中。
# 由于导入了每个函数，可通过名称来调用每个函数，而无须使用句点表示法。
# 然而，使用并非自己编写的大型模块时，最好不要采用这种导入方法。
# 这是因为如果模块中有函数的名称与当前项目中使用的名称相同，可能导致意想不到的结果：
# Python可能遇到多个名称相同的函数或变量，进而覆盖函数，而不是分别导入所有的函数。
# 最佳的做法是，要么只导入需要使用的函数，要么导入整个模块并使用句点表示法。
# 这让代码更清晰，更容易阅读和理解。这里之所以介绍这种导入方法，只是想让你在阅读别人编写的代码时，
# 能够理解类似于下面的import 语句：
# from module_name import *


# 编写函数时，需要牢记几个细节。应给函数指定描述性名称，且只在其中使用小写字母和下划线。
# 描述性名称可帮助你和别人明白代码想要做什么。给模块命名时也应遵循上述约定。
# 每个函数都应包含简要地阐述其功能的注释。该注释应紧跟在函数定义后面，并采用文档字符串格式。
# 文档良好的函数让其他程序员只需阅读文档字符串中的描述就能够使用它。
# 他们完全可以相信代码如描述的那样运行，并且只要知道函数的名称、需要的实参以及返回值的类型，就能在自己的程序中使用它。
# 给形参指定默认值时，等号两边不要有空格：
# def function_name(parameter_0, parameter_1='default value')
# 对于函数调用中的关键字实参，也应遵循这种约定：
# function_name(value_0, parameter_1='value')

# PEP 8建议代码行的长度不要超过79字符，这样只要编辑器窗口适中，就能看到整行代码。
# 如果形参很多，导致函数定义的长度超过了79字符，可在函数定义中输入左括号后按回车键，
# 并在下一行按两次Tab键，从而将形参列表和只缩进一层的函数体区分开来。
# 大多数编辑器会自动对齐后续参数列表行，使其缩进程度与你给第一个参数列表行指定的缩进程度相同：
# def function_name(
# 		parameter_0, parameter_1, parameter_2, 
# 		parameter_3, parameter_4, parameter_5):
# 	function body...

# 如果程序或模块包含多个函数，可使用两个空行将相邻的函数分开，这样将更容易知道前一个函数在什么地方结束，
# 下一个函数从什么地方开始。所有import 语句都应放在文件开头。
# 唯一例外的情形是，在文件开头使用了注释来描述整个程序。